﻿using Hardcodet.Silverlight.Util;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Diagnostics;
using System.IO;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;

namespace depl
{
    [Table]
    public class FavouriteItem
    {
        [Column(IsPrimaryKey = true)]
        public string Name { get; set; }
        
        [Column]
        public string Content { get; set; }

        [Column]
        public DateTime DateAdded { get; set; }
    }

    [Table]
    public class HistoryItem
    {
        [Column(IsPrimaryKey = true, IsDbGenerated = true, DbType = "INT NOT NULL Identity", CanBeNull = false, AutoSync = AutoSync.OnInsert)]
        public string Idx { get; set; }

        [Column]
        public string Name { get; set; }

        [Column]
        public int Id { get; set; }

        [Column]
        public DateTime DateAdded { get; set; }

        public override string ToString()
        {
            return Name;
        }
    }

    public class FavouritesList : ObservableCollection<FavouriteItem>
    {
        public FavouriteItem this[int index]
        {
            get
            {
                // here is where the magic happens, create/load your data on the fly.
                Debug.WriteLine("Requsted item " + index.ToString());
                return new FavouriteItem() { Name = "Song " + index.ToString() };
            }
            set
            {
                throw new NotImplementedException();
            }
        }
    }

    public class EntryStorage: INotifyPropertyChanged
    {
        private static EntryStorage _instance;

        public static EntryStorage Instance
        {
            get
            {
                if (_instance == null)
                {
                    _instance = new EntryStorage();
                }
                return _instance;
            }
        }

        private FavouritesList _favList = new FavouritesList();
        //private List<HistoryItem> _historyList = new List<HistoryItem>();
        //EntryStorageContext _context = new EntryStorageContext();
        int _favCount = 0;
        int _historyCount = 0;
        private bool _hasData = false;
        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public bool HasData
        {
            get
            {
                return _hasData;
            }
            set
            {
                if (value != this._hasData)
                {
                    this._hasData = value;
                    NotifyPropertyChanged();
                }
            }

        }

        public bool ContainsName(string name)
        {
            bool retval = false;
            using (var context = new EntryStorageContext())
            {
                retval = context.ContainsName(name);
            }
            return retval;
        }

        public FavouritesList GetFavs()
        {
            if (_favList.Count > 0)
                return _favList;

            using (var context = new EntryStorageContext())
            {
                IEnumerable < FavouriteItem > dblist = from item in context.Favourites
                        orderby item.DateAdded descending
                        select item;

                if (dblist.Count() > 0)
                    HasData = true;
                else
                    HasData = false;
                foreach (FavouriteItem entry in dblist)
                {
                    _favList.Add(entry);
                    _favCount++;
                }
            }
            Debug.WriteLine("Loaded favourites: "+_favList.Count);
            return _favList;
        }

        public List<HistoryItem> GetHistory()
        {
            using (var context = new EntryStorageContext())
            {
                IEnumerable<HistoryItem> items = from item in context.History
                                                 orderby item.DateAdded descending
                                                 select item;

                _historyCount = items.Count();
                return items.ToList();
            }

        }

        public void StoreHistory(DictEntry entry)
        {
            using (var context = new EntryStorageContext())
            {
                foreach (HistoryItem item in context.History)
                {
                    if (entry.Name == item.Name)
                    {
                        item.DateAdded = DateTime.Now;
                        context.SubmitChanges();
                        return;
                    }
                }

                if (_historyCount >= PivotPage1.MAX_HISTORY_ENTRIES)
                {
                    IEnumerable<HistoryItem> items = from item in context.History
                                                     orderby item.DateAdded
                                                     select item;
                    HistoryItem lastEntry = items.First();
                    Debug.WriteLine("Removing: " + lastEntry.Name);
                    context.History.DeleteOnSubmit(lastEntry);
                    context.SubmitChanges();
                    _historyCount--;

                }

                HistoryItem historyEntry = new HistoryItem
                {
                    Name = entry.Name,
                    Id = entry.Id,
                    DateAdded = DateTime.Now
                };
                Debug.WriteLine("Adding: " + historyEntry.Name);
                context.History.InsertOnSubmit(historyEntry);
                context.SubmitChanges();
                _historyCount++;
            }
        }

        public void ClearHistory()
        {
            _historyCount = 0;
            using (var context = new EntryStorageContext())
            {
                context.History.DeleteAllOnSubmit(context.History);
                context.SubmitChanges();
            }
        }
        public void StoreFavourite(Entry entry)
        {
            using (var context = new EntryStorageContext())
            {
                if (_favCount >= PivotPage1.MAX_FAVOURITES_ENTRIES)
                {
                    IEnumerable<FavouriteItem> items = from item in context.Favourites
                                                     orderby item.DateAdded
                                                     select item;
                    FavouriteItem lastEntry = items.First();
                    Debug.WriteLine("Removing: " + lastEntry.Name);
                    context.Favourites.DeleteOnSubmit(lastEntry);
                    context.SubmitChanges();
                    _favList.Remove(_favList.Last());
                    _favCount--;
                
                }
                FavouriteItem favEntry = new FavouriteItem
                {
                    Name = entry.Name,
                    Content = entry.Content,
                    DateAdded = DateTime.Now
                };

                HasData = true;
                _favList.Insert(0, favEntry);
                _favCount++;
                context.Favourites.InsertOnSubmit(favEntry);
                context.SubmitChanges();
            }
        }

        public void DeleteFavourite(FavouriteItem fav)
        {
            _favList.Remove(fav);
            _favCount--;
            if (_favList.Count == 0)
                HasData = false;
            using (var context = new EntryStorageContext())
            {
                context.Favourites.Attach(fav);



                context.Favourites.DeleteOnSubmit(fav);
                context.SubmitChanges();
            }
        }

    }

    public class EntryStorageContext : DataContext
    {
        public EntryStorageContext()
            : base("Data Source=isostore:/EntryStorageDB.sdf")
        {
            if(!DatabaseExists())
            {
                CreateDatabase();
            }
        }

        public bool ContainsName(string name)
        {
            IEnumerable<FavouriteItem> retrievedFavs = from FavouriteItem fav in Favourites where fav.Name == name select fav;
            return retrievedFavs.Count() > 0;
        }

        public Table<FavouriteItem> Favourites;
        public Table<HistoryItem> History;
    }


}
